package com.llh.uua.validation

import com.llh.uua.validation.annotation.ValidPassword
import org.passay.*
import org.passay.spring.SpringMessageResolver
import org.springframework.stereotype.Component
import javax.validation.ConstraintValidator
import javax.validation.ConstraintValidatorContext

/**
 * 自定义密码验证器
 *
 * Created At 2021/3/14 15:50
 * @author llh
 */
class PasswordConstraintValidator(private val messageResolver: SpringMessageResolver) :
    ConstraintValidator<ValidPassword, String> {

    override fun initialize(constraintAnnotation: ValidPassword?) {
        super.initialize(constraintAnnotation)
    }

    override fun isValid(password: String, context: ConstraintValidatorContext): Boolean {
        val validator = PasswordValidator(
            messageResolver,
            // 长度规则：8 - 30 位
            LengthRule(8, 30),
            // 至少有一个大写字母
            CharacterRule(EnglishCharacterData.UpperCase, 1),
            // 至少有一个小写字母
            CharacterRule(EnglishCharacterData.LowerCase, 1),
            // 至少有一个数字
            CharacterRule(EnglishCharacterData.Digit, 1),
            // 至少有一个特殊字符
            CharacterRule(EnglishCharacterData.Special, 1),
            // 不允许连续 3 个字母，按字母表顺序
            // alphabetical is of the form 'abcde', numerical is '34567', qwery is 'asdfg'
            // the false parameter indicates that wrapped sequences are allowed; e.g. 'xyzabc'
            IllegalSequenceRule(EnglishSequenceData.Alphabetical, 5, false),
            // 不允许 5 个连续数字
            IllegalSequenceRule(EnglishSequenceData.Numerical, 5, false),
            // 不允许 QWERTY 键盘上的 5 个连续相邻的按键所代表的字符
            IllegalSequenceRule(EnglishSequenceData.USQwerty, 5, false),
            // 不允许包含空格
            WhitespaceRule()
        )
        val result = validator.validate(PasswordData(password))
        if (result.isValid) {
            return true
        }
        context.disableDefaultConstraintViolation()
        context
            .buildConstraintViolationWithTemplate(validator.getMessages(result).joinToString(","))
            .addConstraintViolation()
        return false
    }
}